#include <iostream>
#include <string>
#include <fstream>
#include <cmath>
#include <vector>
#include <string>
#include <stdio.h>
#include <fstream>
#include <map>
#include <sstream>

#include "agg_basics.h"
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_pixfmt_rgb.h"
#include "platform/agg_platform_support.h"
#include "ctrl/agg_slider_ctrl.h"
#include "ctrl/agg_cbox_ctrl.h"
#include "agg_glyph_raster_bin.h"
#include "agg_renderer_raster_text.h"
#include "agg_embedded_raster_fonts.h"
#include "agg_rounded_rect.h"
#include "agg_span_allocator.h"
#include "agg_span_gradient.h"
#include "agg_span_interpolator_linear.h"

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdlib.h>
#include <pthread.h>
#include "argslib.h"
#include <math.h>


#include "CApp.h"
#include "CNetwork.h"
#include "CCommand.h"
#include "CNode.h"
#include "CConsole.h"
#include "CSendMess.h"

int i_winWidth;
int i_winHeight;

std::string pathTcl;

CNetwork *net;
CConsole console;

pthread_mutex_t mutex;
pthread_mutex_t MX_RWNet;
pthread_mutex_t MX_RWMess;

std::vector< CSendMess* > v_sendMess;

enum flip_y_e { flip_y = false };

typedef agg::pixfmt_bgr24 pixfmt;
typedef agg::renderer_base<pixfmt> ren_base;
typedef agg::glyph_raster_bin<agg::rgba8> glyph_gen;
typedef agg::rgba8 color;
typedef agg::gradient_linear_color<color> color_func_type;
typedef agg::gradient_x gradient_func_type;
typedef agg::span_allocator<color> span_allocator_type;
typedef agg::span_interpolator_linear<> interpolator_type;
typedef agg::span_gradient<color, interpolator_type, gradient_func_type, color_func_type> span_gradient_type;
typedef agg::span_interpolator_linear<> interpolator_type;

agg::trans_affine gradient_affine(double x1, double y1, double x2, double y2,
double gradient_d2 = 100.0)
{
	agg::trans_affine mtx;
	double dx = x2 - x1;
	double dy = y2 - y1;
	mtx.reset();
	mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2);
	mtx *= agg::trans_affine_rotation(atan2(dy, dx));
	mtx *= agg::trans_affine_translation(x1, y1);
	mtx.invert();
	return mtx;
}







void *sendMessages(void *p_void){
  int i = 0;
  char receive[800];
  std::string line;
  std::stringstream stream;
  std::vector< CSendMess* >::iterator it;

  printf("> Thread d'ecritue initialise\n");
  while(1){
    usleep(100000);

    pthread_mutex_lock(&MX_RWMess);
    i=0;
    while(i<v_sendMess.size()){
      v_sendMess[i]->m_i_time--;
      //printf("-%s-\n",line.c_str());
      if(v_sendMess[i]->m_i_time<=0){
        //printf("-%s-\n",v_sendMess[i]->m_str_mess.c_str());
        write(v_sendMess[i]->m_CNode_dst->in[1], v_sendMess[i]->m_str_mess.c_str(), v_sendMess[i]->m_str_mess.size());
        it = v_sendMess.begin()+i;
        v_sendMess.erase(it);
      }else{
        i++;
      }
    }
    pthread_mutex_unlock(&MX_RWMess);
    //app.force_redraw();
  }
}

CApp app(agg::pix_format_bgr24, flip_y);

// Main -----------------------------------------------------------------------
int agg_main(int argc, char* argv[]){
  pthread_t filsSendMess;
  i_winWidth=800;
  i_winHeight=600;

  // Usage
  if(argc < 2 || argc == 3){
    printf("usage: %s <path tcl> [width height]\n",argv[0]);
    return -1;
  }

  // Recuperation des dimensions de la fenetre
  if(argc == 4){
    i_winWidth = atoi(argv[2]);
    i_winHeight = atoi(argv[3]);
  }

  // Path de l'application tcl
  pathTcl = argv[1];

  // Affichage de l'initialisation
  printf("> Parametres du simulateur\n\tlargeur: %i, hauteur: %i\n\tpath: %s\n", i_winWidth, i_winHeight, pathTcl.c_str());

  // Initialisation du réseau
  net = new CNetwork();

	//net->openNetwork("los");

  // Initialisation de la fenetre
  app.refreshNetwork();
  app.caption("Network Simulation");

  printf("> Initialisation du simulateur\n");
  // Ouverture de la fenetre agg
  if(app.init(i_winWidth, i_winHeight, agg::window_resize)){
    printf("> Lancement du thread d'ecriture ...\n");

    // Creation du thread d'ecriture
    if (pthread_create(&filsSendMess, NULL, sendMessages, NULL)){
      perror("pthread_create");
      exit(EXIT_FAILURE);
    }

    printf("> Lancement du simulateur\n");
    return app.run();
  }

  return 0;
}
